

import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_libserialport/flutter_libserialport.dart';
import 'package:logger/logger.dart';
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:ponydata_desk/utils/utils.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

extension IntToString on int {
  String toHex() => '0x${toRadixString(16)}';
  String toPadded([int width = 3]) => toString().padLeft(width, '0');
  String toTransport() {
    switch (this) {
      case SerialPortTransport.usb:
        return 'USB';
      case SerialPortTransport.bluetooth:
        return 'Bluetooth';
      case SerialPortTransport.native:
        return 'Native';
      default:
        return 'Unknown';
    }
  }
}
class _HomePageState extends State<HomePage> {
  CustomPopupMenuController _controller = CustomPopupMenuController();

  CustomPopupMenuController _baudRateController = CustomPopupMenuController();

  CustomPopupMenuController _stopBitsController = CustomPopupMenuController();

  CustomPopupMenuController _bitsController = CustomPopupMenuController();

  CustomPopupMenuController _paritysController = CustomPopupMenuController();

  TextEditingController _macController =  TextEditingController();

  // 最后操作时间
  int lastSendEvent=DateTime.now().millisecondsSinceEpoch;


  String portName="";


  var availablePorts = [];

  var baudRates = [38400,115200,];

  var stopBitList = [1,2,];

  var bitList = [8,7,6,5];

  var paritys = [1,];

  // 奇偶校验
  int parity =0;
  int baudRate = 0;
  int bits = 0;
  int stopBits = 0;

  SerialPort? _port ;

  bool isOpen = false;

  String _text="";

  String _command = "";

  int  sendTimeout =0;
  int sendTime = 0;

  @override
  void initState() {
    super.initState();

    refashConfig();

  }
  void refashText(){
    if(mounted){
      setState(() {
        _text="";
      });
    }
  }
  void refashCommandText(){
    if(mounted){
      setState(() {
        _command="";
        _macController.text="";
      });
    }
  }
  void refashConfig(){
    if(isOpen){
      BotToast.showText(text: "请先关闭串口连接");

      return;
    }
    if(mounted){
      setState(() {
        if(availablePorts.isNotEmpty){
          portName = availablePorts.first;
        }
         parity = paritys.first;
         stopBits = stopBitList.first;
         baudRate =  baudRates.first;
         bits = bitList.first;
      });
    }
  }

  void initPorts() {
    if(isOpen){
      BotToast.showText(text: "请先关闭串口连接");
      return;
    }
    if(_port!=null){
      _port!.close();
      _port = null;
    }
    _port = null;
    setState(() => availablePorts = SerialPort.availablePorts);
    if(availablePorts.isNotEmpty){
      if(mounted){
        setState(() {
          portName = availablePorts.first;
        });
      }
    }


    BotToast.showText(text: "串口信息获取完成");

  }
  void openPort(){
    if(portName==null||portName.length==0){
      BotToast.showText(text: "请先选择串口");
      return;
    }

    if(!checkEventFrequency()){
      return;
    }

    SerialPort port = SerialPort(portName);
    port.config.baudRate = baudRate;
    port.config.bits = bits;
    port.config.parity = parity;
    port.config.stopBits = stopBits;
    _readData(port);
  }
  bool checkEventFrequency(){

  int current =DateTime.now().millisecondsSinceEpoch;

  if(current-lastSendEvent<1000){
    BotToast.showText(text: "操作不能太频繁");
    return false;
  }
  lastSendEvent = current;
  return true;
}

  void closeSerial(){

    if(!checkEventFrequency()){
      return;
    }

    if(_port!=null){
      bool isClose = _port!.close();
      if(isClose){
        BotToast.showText(text: "串口关闭成功");
        _port=null;
      }else{
        BotToast.showText(text: "串口关闭失败");
      }
      if(mounted){
        setState(() {
          isOpen = !isClose;
        });
      }
    }
  }

  void _readData(SerialPort port) async {
    // 读数据
    final reader = SerialPortReader(port, timeout: 10);
    List<String> list = [];
    // if (!port.openReadWrite()) {
    //   print(SerialPort.lastError);
    //   return;
    // }
    if( port.openReadWrite()){
      if(mounted){
        setState(() {
          isOpen = true;
        });
      }
      BotToast.showText(text: "串口打开成功");
      _port =port;

    }else{
      if(mounted){
        setState(() {
          isOpen = false;
        });
      }
      BotToast.showText(text: "串口打开失败");
    }

    StringBuffer buffer = StringBuffer();
    int timeout = DateTime.now().millisecondsSinceEpoch;
    Timer.periodic(Duration(milliseconds: 5), (timer) {
      if (list.isNotEmpty) {
        int lastTime = DateTime.now().millisecondsSinceEpoch - timeout;
        // if (lastTime > readTime) {
        //
        // }
        DateTime dateTime= DateTime.now();

        for (var d in list) {
          buffer.write(d.toString());
        }

        String value =  _text+"\n" +"${dateTime.toString()}---" + buffer.toString();

        if(value.length>50000){
          value =  value.substring(value.length-50000);
        }

        if(mounted){
          setState(() {
            _text = value;
          });
        }
        buffer.clear();
        list.clear();
      }
    });
    reader.stream.listen((data) {
      String hexString = data.map((byte) => byte.toRadixString(16)).join();
      //print('receivedHex: ${hexString.toUpperCase()}'); // 转换为16进制
      list.add(hexString);
      timeout = DateTime.now().millisecondsSinceEpoch;
    });
    //执行接下来的操作
  }

  void senData() async {
    if(isOpen==false || _port==null){
      BotToast.showText(text: "请打开串口");
      return ;
    }
    if (_command==null || _command.length==0) {
      BotToast.showText(text: "请输入命令");
      return;
    }
    var logger = Logger();
    // sendTime = DateTime.now().millisecondsSinceEpoch;
    // int lastSendTimeout=DateTime.now().millisecondsSinceEpoch-sendTimeout;
    // print(lastSendTimeout);
    // if(lastSendTimeout>sendTime){
    //   List<int> dataList = [];
    //   int len = _command.length ~/ 2;
    //   for (int i = 0; i < len; i++) {
    //     String data = _command.trim().substring(2 * i, 2 * (i + 1));
    //     int? d = Utils.hexToInt(data);
    //     dataList.add(d!);
    //   }
    //   print('发送数据${_command}');
    //
    //   print('发送数据${dataList.toString()}');
    //   var bytes = Uint8List.fromList(dataList);

    // List<int> commandBytes = [
    //   0x0A, // LF
    //   0x52, // R
    //   0x33, // 3
    //   0x2C, // ,
    //   0x42, // B
    //   0x46, // F
    //   0x2C, // ,
    //   0x31, // 1
    //   0x0D, // CR
    // ];
    List<int> commandBytes = [
      0x0A, // LF
      0x52, // R
      0x31, // 1
      0x2C, // ,
      0x32, // 2
      0x2C, // ,
      0x36, // 6
      0x0D, // CR
    ];


    Uint8List command = Utils().stringToUint8List("<LF>R1,2,6<CR>");
     // Uint8List.fromList(commandBytes);

    int state = _port!.write(command);
      print('发送数据state-${state}');

      sendTimeout = DateTime.now().millisecondsSinceEpoch;
    // }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar:  AppBar(
      // TRY THIS: Try changing the color here to a specific color (to
      // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
      // change color while the other colors stay the same.
      backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      // Here we take the value from the MyHomePage object that was created by
      // the App.build method, and use it to set our appbar title.
      title: Text("串口工具"),
    ),body: Scrollbar(
      child:Column(crossAxisAlignment: CrossAxisAlignment.start,children: [
        Container(height: 500,child: Row(children: [
          Expanded(child:
          Container(height: 500,padding: EdgeInsets.all(10), color: Colors.black,child:SingleChildScrollView(child:Text(_text,textAlign: TextAlign.start,maxLines: 1000,overflow: TextOverflow.clip,style: TextStyle(color: Colors.white,fontSize: 12),),),),),
          Card(child:Container(padding: EdgeInsets.all(10) ,width: 250,child:Column(children: [

            Container(child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("串口",style: Theme.of(context).textTheme.titleSmall,),),
              Container(padding: EdgeInsets.only(left: 10),decoration: BoxDecoration(
                  color: Theme.of(context).dividerColor,
                  borderRadius: BorderRadius.circular(1)),height: 48,width: 160,child:  CustomPopupMenu(
                child: Container(
                  child: Row(
                    children: [
                      Text(
                        portName,
                        style: Theme.of(context).textTheme.titleSmall,
                      ),
                      Icon(Icons.keyboard_arrow_down),
                    ],
                  ),
                ),
                arrowColor: Colors.white,
                menuBuilder: () => ClipRRect(
                  borderRadius: BorderRadius.circular(5),
                  child: Container(
                    color: Colors.white,
                    child: IntrinsicWidth(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children:availablePorts!
                            .map(
                              (item) => GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onTap: () {
                              _controller.hideMenu();
                              if (mounted) {
                                setState(() {
                                  portName = item;
                                });
                              }
                              // _onRefresh();
                            },
                            child: Container(
                              height: 40,
                              padding:
                              EdgeInsets.symmetric(horizontal: 20),
                              child: Row(
                                children: <Widget>[
                                  Container(
                                    margin: EdgeInsets.only(left: 1),
                                    padding: EdgeInsets.symmetric(
                                        vertical: 10),
                                    child: Text(
                                      item!,
                                      style: TextStyle(
                                        color: Colors.black,
                                        fontSize: 12,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        )
                            .toList(),
                      ),
                    ),
                  ),
                ),
                pressType: PressType.singleClick,
                verticalMargin: -10,
                controller: _controller,
              ),

              ),
            ],)),

            // 波特率
            Container(margin: EdgeInsets.only(top: 10),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("波特率",style: Theme.of(context).textTheme.titleSmall,),),
              Container(padding: EdgeInsets.only(left: 10),decoration: BoxDecoration(
                  color: Theme.of(context).dividerColor,
                  borderRadius: BorderRadius.circular(1)),height: 48,width: 160,child:  CustomPopupMenu(
                child: Container(
                  child: Row(
                    children: [
                      Text(
                      "${baudRate}" ,
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                      Icon(Icons.keyboard_arrow_down),
                    ],
                  ),
                ),
                arrowColor: Colors.white,
                menuBuilder: () => ClipRRect(
                  borderRadius: BorderRadius.circular(5),
                  child: Container(
                    color: Colors.white,
                    child: IntrinsicWidth(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children:baudRates!
                            .map(
                              (item) => GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onTap: () {
                              _baudRateController.hideMenu();
                              if (mounted) {
                                setState(() {
                                  baudRate = item;
                                });
                              }
                              // _onRefresh();
                            },
                            child: Container(
                              height: 40,
                              padding:
                              EdgeInsets.symmetric(horizontal: 20),
                              child: Row(
                                children: <Widget>[
                                  Container(
                                    margin: EdgeInsets.only(left: 1),
                                    padding: EdgeInsets.symmetric(
                                        vertical: 10),
                                    child: Text(
                                     "${item}" ,
                                      style: TextStyle(
                                        color: Colors.black,
                                        fontSize: 12,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        )
                            .toList(),
                      ),
                    ),
                  ),
                ),
                pressType: PressType.singleClick,
                verticalMargin: -10,
                controller: _baudRateController,
              ),

              ),
            ],)),
            // 停止位
            Container(margin: EdgeInsets.only(top: 10),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("停止位",style: Theme.of(context).textTheme.titleSmall,),),
              Container(padding: EdgeInsets.only(left: 10),decoration: BoxDecoration(
                  color: Theme.of(context).dividerColor,
                  borderRadius: BorderRadius.circular(1)),height: 48,width: 160,child:  CustomPopupMenu(
                child: Container(
                  child: Row(
                    children: [
                      Text(
                       "${stopBits}" ,
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                      Icon(Icons.keyboard_arrow_down),
                    ],
                  ),
                ),
                arrowColor: Colors.white,
                menuBuilder: () => ClipRRect(
                  borderRadius: BorderRadius.circular(5),
                  child: Container(
                    color: Colors.white,
                    child: IntrinsicWidth(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children:stopBitList!
                            .map(
                              (item) => GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onTap: () {
                              _stopBitsController.hideMenu();
                              if (mounted) {
                                setState(() {
                                  stopBits =  item;
                                });
                              }
                              // _onRefresh();
                            },
                            child: Container(
                              height: 40,
                              padding:
                              EdgeInsets.symmetric(horizontal: 20),
                              child: Row(
                                children: <Widget>[
                                  Container(
                                    margin: EdgeInsets.only(left: 1),
                                    padding: EdgeInsets.symmetric(
                                        vertical: 10),
                                    child: Text(
                                      "${item}" ,
                                      style: TextStyle(
                                        color: Colors.black,
                                        fontSize: 12,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        )
                            .toList(),
                      ),
                    ),
                  ),
                ),
                pressType: PressType.singleClick,
                verticalMargin: -10,
                controller: _stopBitsController,
              ),

              ),
            ],)),
            // 数据位
            Container(margin: EdgeInsets.only(top: 10),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("数据位",style: Theme.of(context).textTheme.titleSmall,),),
              Container(padding: EdgeInsets.only(left: 10),decoration: BoxDecoration(
                  color: Theme.of(context).dividerColor,
                  borderRadius: BorderRadius.circular(1)),height: 48,width: 160,child:  CustomPopupMenu(
                child: Container(
                  child: Row(
                    children: [
                      Text(
                        "${bits}" ,
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                      Icon(Icons.keyboard_arrow_down),
                    ],
                  ),
                ),
                arrowColor: Colors.white,
                menuBuilder: () => ClipRRect(
                  borderRadius: BorderRadius.circular(5),
                  child: Container(
                    color: Colors.white,
                    child: IntrinsicWidth(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children:bitList!
                            .map(
                              (item) => GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onTap: () {
                              _bitsController.hideMenu();
                              if (mounted) {
                                setState(() {
                                  bits =  item.toInt();
                                });
                              }
                              // _onRefresh();
                            },
                            child: Container(
                              height: 40,
                              padding:
                              EdgeInsets.symmetric(horizontal: 20),
                              child: Row(
                                children: <Widget>[
                                  Container(
                                    margin: EdgeInsets.only(left: 1),
                                    padding: EdgeInsets.symmetric(
                                        vertical: 10),
                                    child: Text(
                                      "${item}" ,
                                      style: TextStyle(
                                        color: Colors.black,
                                        fontSize: 12,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        )
                            .toList(),
                      ),
                    ),
                  ),
                ),
                pressType: PressType.singleClick,
                verticalMargin: -10,
                controller: _bitsController,
              ),

              ),
            ],)),
            // 校验位
            Container(margin: EdgeInsets.only(top: 10),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("校验位",style: Theme.of(context).textTheme.titleSmall,),),
              Container(padding: EdgeInsets.only(left: 10),decoration: BoxDecoration(
                  color: Theme.of(context).dividerColor,
                  borderRadius: BorderRadius.circular(1)),height: 48,width: 160,child:  CustomPopupMenu(
                child: Container(
                  child: Row(
                    children: [
                      Text(
                        "${parity}" ,
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                      Icon(Icons.keyboard_arrow_down),
                    ],
                  ),
                ),
                arrowColor: Colors.white,
                menuBuilder: () => ClipRRect(
                  borderRadius: BorderRadius.circular(5),
                  child: Container(
                    color: Colors.white,
                    child: IntrinsicWidth(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children:paritys!
                            .map(
                              (item) => GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onTap: () {
                              _paritysController.hideMenu();
                              if (mounted) {
                                setState(() {
                                  parity =  item.toInt();
                                });
                              }
                              // _onRefresh();
                            },
                            child: Container(
                              height: 40,
                              padding:
                              EdgeInsets.symmetric(horizontal: 20),
                              child: Row(
                                children: <Widget>[
                                  Container(
                                    margin: EdgeInsets.only(left: 1),
                                    padding: EdgeInsets.symmetric(
                                        vertical: 10),
                                    child: Text(
                                      "${item}" ,
                                      style: TextStyle(
                                        color: Colors.black,
                                        fontSize: 12,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        )
                            .toList(),
                      ),
                    ),
                  ),
                ),
                pressType: PressType.singleClick,
                verticalMargin: -10,
                controller: _paritysController,
              ),

              ),
            ],)),

            // 状态
            Container(margin: EdgeInsets.only(top: 10),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [
              Container(width: 60,child:
              Text("状态",style: Theme.of(context).textTheme.titleSmall,),),
              Container(width: 160,child: Text( isOpen?"已打开":"未连接",style: TextStyle(color:isOpen?Colors.greenAccent:Theme.of(context).colorScheme.error),),),

            ],)),

            Container(margin: EdgeInsets.only(top: 10),width: 160,child: OutlinedButton(onPressed: refashConfig, child:  Text("重置",style:  TextStyle(fontWeight: FontWeight.w500),)),),

            Container(margin: EdgeInsets.only(top: 10),width: 160,child: OutlinedButton(onPressed: refashText, child:  Text("清空数据",style:  TextStyle(fontWeight: FontWeight.w500),)),),

            Container(margin: EdgeInsets.only(top: 10),width: 160,child: ElevatedButton(onPressed:  isOpen?closeSerial:openPort,
                child:  Text( isOpen?"关闭串口连接":"连接串口",style: TextStyle(fontWeight: FontWeight.w600,color: !isOpen?Colors.greenAccent:Theme.of(context).colorScheme.error),)),),

          ],),))

        ],),),

       Container(margin: EdgeInsets.only(left: 5),height:120 ,width: 720,child: Card(child: Container(child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [

         Container(width: 500,height: 100 ,padding: EdgeInsets.all(2),color:Theme.of(context).canvasColor,child:
           TextFormField(
             obscureText: false,
             controller: _macController,
             keyboardType: TextInputType.text,
             maxLines: 10,
             decoration: InputDecoration(
               fillColor: Theme.of(context).canvasColor,
               hintText: '清输入命令',
               // labelText:
               labelStyle:TextStyle(fontSize: 16,color:Color(0x4d3c3c43)),

               focusedBorder: UnderlineInputBorder(
                 borderSide: BorderSide(
                   color: Color(0xFF3572FF), //边线颜色为黄色
                   width: 1, //边线宽度为2
                 ),
               ),
             ),
             onChanged: (text) {
               print("enen${text}");
               setState(() {
                 _command = text;
               });
             },
           ),),
          Container(child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [
            Container(margin: EdgeInsets.only(top: 10),width: 160,child: OutlinedButton(onPressed: refashCommandText, child:  Text("清空命令",style:  TextStyle(fontWeight: FontWeight.w500),)),),

            Container(margin: EdgeInsets.only(top: 10),width: 160,child: ElevatedButton(onPressed: senData,
                child:  Text( "发送",style: TextStyle(fontWeight: FontWeight.w600,color: Colors.greenAccent),)),),

          ],),)
       ],),),),)
      ],)
      //   ListView(
      //   children: [
      //     for (final address in availablePorts)
      //       Builder(builder: (context) {
      //         final port = SerialPort(address);
      //         return ExpansionTile(
      //           title: Text(address),
      //           children: [
      //             CardListTile('Description', port.description),
      //             CardListTile('Transport', port.transport.toTransport()),
      //             CardListTile('USB Bus', port.busNumber?.toPadded()),
      //             CardListTile('USB Device', port.deviceNumber?.toPadded()),
      //             CardListTile('Vendor ID', port.vendorId?.toHex()),
      //             CardListTile('Product ID', port.productId?.toHex()),
      //             CardListTile('Manufacturer', port.manufacturer),
      //             CardListTile('Product Name', port.productName),
      //             CardListTile('Serial Number', port.serialNumber),
      //             CardListTile('MAC Address', port.macAddress),
      //           ],
      //         );
      //       }),
      //   ],
      // ),
    ),
      floatingActionButton: FloatingActionButton(
        child:Icon(Icons.refresh),
        onPressed: initPorts,
      ),
    );
  }
}
class CardListTile extends StatelessWidget {
  final String name;
  final String? value;

  CardListTile(this.name, this.value);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        title: Text(value ?? 'N/A'),
        subtitle: Text(name),
      ),
    );
  }
}
